package com.vipsoft.base.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ConvertUtil {

    /**
     * 字符转 Integer 默认返回NULL
     *
     * @param param
     * @return
     */
    public static Integer toInteger(String param) {
        return toInteger(param, null);
    }

    /**
     * 字符转 Integer
     *
     * @param param  字符
     * @param defVal 默认值
     * @return
     */
    public static Integer toInteger(String param, Integer defVal) {
        try {
            return Integer.valueOf(param);
        } catch (Exception e) {
            e.printStackTrace();
            return defVal;
        }
    }

    /**
     * 字符转 String 默认返回 ""
     *
     * @param param
     * @return
     */
    public static String toString(Object param) {
        return toString(param, "");
    }

    /**
     * 字符转 String
     *
     * @param param  字符
     * @param defVal 默认值
     * @return
     */
    public static String toString(Object param, String defVal) {
        try {
            return ObjectUtil.isEmpty(param) ? defVal : param.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return defVal;
        }
    }

    /**
     * 在 某个字符前，插入 XX 字符
     *
     * @param insertStr
     * @param beforeStr
     * @return
     */
    public static String insertStrBeforeStr(String originalStr, String insertStr, String beforeStr) {
        if (StrUtil.isEmpty(originalStr)) {
            return originalStr;
        }
        int splitIndex = originalStr.lastIndexOf(beforeStr);
        if (splitIndex != -1) {
            String bStr = originalStr.substring(0, splitIndex);
            String eStr = originalStr.substring(splitIndex);
            return StrUtil.format("{}{}{}", bStr, insertStr, eStr);
        } else {
            return originalStr;  // 如果文件名没有扩展名，返回原文件名
        }
    }

    /***
     * 根据出生日期转换年龄
     * 异常返回NULL，不影响业务系统数据的存储
     * @param birthdate
     * @return
     */
    public static Integer toAge(String birthdate) {
        try {
            return DateUtil.ageOfNow(birthdate);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /***
     * 根据出生日期转换年龄
     * 异常返回NULL，不影响业务系统数据的存储
     * @param birthdate
     * @return
     */
    public static Integer toAge(Date birthdate) {
        try {
            return DateUtil.ageOfNow(birthdate);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    /***
     * 根据字符串转日期，
     * @return 如果转失败返回 null ，不影响业务系统数据的存储
     */
    public static DateTime toDateTime(String dateStr) {
        try {
            if (StrUtil.isEmpty(dateStr)) {
                return null;
            }
            return DateUtil.parse(dateStr, "yyyy-MM-dd HH:mm:ss");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /***
     * 根据字符串转日期，
     * @return 如果转失败返回 null ，不影响业务系统数据的存储
     */
    public static DateTime toDateTime(String dateStr, String format) {
        try {
            if (StrUtil.isEmpty(dateStr)) {
                return null;
            }
            return DateUtil.parse(dateStr, format);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 字符转 base 64
     */
    public static String toBase64(String value) {
        try {
            Base64.Encoder encoder = Base64.getEncoder();
            return encoder.encodeToString(value.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            System.out.println(value);
            e.printStackTrace();
        } finally {
        }
        return "";
    }


    /**
     * 根据字符串，找到对应属性，获取Annotation的值
     *
     * @param clazz           被查找对象
     * @param propertyName    被查找属性
     * @param annotationClass 注释类
     * @param methodNames     注释类的方法
     * @param <T>
     * @return
     */
    public static <T extends Annotation> String getAnnotationValue(Class<?> clazz, String propertyName, Class<T> annotationClass, String... methodNames) {
        try {
            // 首先检查当前类中的字段 -- 仅能获取类本身的属性成员（包括私有、共有、保护）
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                if (field.getName().equals(propertyName)) {
                    T annotation = field.getAnnotation(annotationClass);
                    if (annotation != null) {
                        // 这里假设注解有一个名为 "value" 的方法返回 String 类型
                        // 你需要根据实际的注解定义来调整
                        java.lang.reflect.Method valueMethod = annotationClass.getMethod(methodNames.length > 0 ? methodNames[0] : "value");
                        return (String) valueMethod.invoke(annotation);
                    }
                }
            }

            // 如果没有在当前类中找到，就检查父类 -- 在获取父类的私有属性时，要通过getSuperclass的之后再通过getDeclaredFiled获取。
            Class<?> superclass = clazz.getSuperclass();
            while (superclass != null) {
                Field[] superDeclaredFields = superclass.getDeclaredFields();
                for (Field field : superDeclaredFields) {
                    if (field.getName().equals(propertyName)) {
                        T annotation = field.getAnnotation(annotationClass);
                        if (annotation != null) {
                            java.lang.reflect.Method valueMethod = annotationClass.getMethod(methodNames.length > 0 ? methodNames[0] : "value");
                            return (String) valueMethod.invoke(annotation);
                        }
                    }
                }
                superclass = superclass.getSuperclass();  // 递归搜索父类
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null; // 如果没有找到对应的注解或属性，返回null
    }


    // 定义单位常量
    private static final long KB = 1024L;
    private static final long MB = KB * 1024L;
    private static final long GB = MB * 1024L;
    private static final long TB = GB * 1024L;

    public static String readableFileSize(long bytes) {
        if (bytes >= TB) {
            return String.format("%.2f TB", (double) bytes / TB);
        } else if (bytes >= GB) {
            return String.format("%.2f GB", (double) bytes / GB);
        } else if (bytes >= MB) {
            return String.format("%.2f MB", (double) bytes / MB);
        } else if (bytes >= KB) {
            return String.format("%.2f KB", (double) bytes / KB);
        } else {
            return String.format("%d B", bytes);
        }
    }

    /**
     * 方法一
     * @param size
     * @return
     */
    public static String toSize(long size) {
        if (size <= 0) {
            return "0";
        }
        final String[] units = new String[]{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,###.##").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    /**
     * 将数据库中的 多级嵌套 @MapKey 转成 key,value
     * @param dbMapkey
     * @return
     */
    public static Map<String, Object> toMap(Map<String, Map<String, Object>> dbMapkey) {
        Map<String, Object> result = new HashMap<>();
        for (Map<String, Object> map : dbMapkey.values()) {
            result.put(map.get("name").toString(), map.get("value"));
        }
        return result;
    }
}
